import { Injectable } from '@nestjs/common';
import { MongodbService } from '../../../shared/mongodb/mongodb.service';
import { SseService } from '../../sse/sse.service';
import { CacheService } from '../../../shared/redis/cache.service';
import { HttpRequestService } from '../../../shared/helper/httpRequest.service';
import * as mongoose from 'mongoose';
import { DataBaseLinkService } from '../../../shared/databaselink/databaselink.service';
import { BusinessException } from '~/common/exceptions/biz.exception';
import { ErrorEnum } from '~/constants/error-code.constant';
import * as _ from 'lodash';
import { error } from 'console';
import { OperationLogService } from '../../system/log/services/operation-log.service';

@Injectable()
export class VarTestService {
  constructor(
    private readonly mongodbService: MongodbService,
    private readonly sseService: SseService,
    private readonly cacheService: CacheService,
    private readonly httpRequestService: HttpRequestService,
    private dataBaseLinkService: DataBaseLinkService,
    private readonly operationLogService: OperationLogService
  ) {}

  getRandomDateThisYear(): Date {
    const now = new Date();
    const year = now.getFullYear(); // 获取当前年份

    // 设置为今年的 1 月 1 日
    const startDate = new Date(year, 0, 1);

    // 设置为今年的 12 月 31 日
    const endDate = new Date(year, 11, 31);

    // 生成介于两个日期之间的随机时间戳
    const randomTimestamp =
      startDate.getTime() +
      Math.random() * (endDate.getTime() - startDate.getTime());

    return new Date(randomTimestamp);
  }

  //插入数据
  async varAdd(body) {
    let insertObj = {
      varString: 'test' + Math.floor(Math.random() * 100),
      varMysqlId: Math.floor(Math.random() * 100),
      varBool: Math.floor(Math.random() * 100) % 2 === 0 ? true : false,
      varNumber: Math.floor(Math.random() * 100),
      varStringArray:
        Math.floor(Math.random() * 100) % 2 === 0 ? ['a', 'b'] : ['d', 'c'],
      varNumberArray: [Math.random(), Math.random()],
      varEnumStatus:
        Math.floor(Math.random() * 100) % 2 === 0 ? '正常' : '不正常',
      //今年的随机时间
      varDate: this.getRandomDateThisYear(),
      varObject: { key: `value-${Math.random().toString(36).substring(7)}` },
      varObjectArray: [
        { name: `obj-${Math.random().toString(36).substring(7)}` },
      ],
      varObjectHasType: { name: 'example', value: 1 },
      varObjectArrayHasType: [{ itemName: 'item', itemValue: 10 }],
      varSubDocument: { fileName: 'test.txt', filePath: '/files/test.txt' },
      varDocumentArray: [{ fileName: 'file1.txt', filePath: '/files/1.txt' }],
      varObjectId: '685291fe5ed62131620e08c7',
      varObjectIdOrigin: new mongoose.Types.ObjectId(
        '685291fe5ed62131620e08c7'
      ),
    };
    await this.mongodbService.VarTestModel.create(insertObj);
    const list = await this.mongodbService.VarTestModel.aggregate([
      { $project: { _id: 0, __v: 0 } },
    ]);
    return list;
  }
  //获取列表 根据查询条件 - 使用管道
  async varList(dto, req) {
    const {
      searchValue,
      userId,
      varBool,
      varDateStart,
      varDateEnd,
      varEnumStatus,
      varNumber,
      varNeString,
      varStringArray,
      varNumberArray,
      varObject,
      varObjectId,
      varString,
      varSubDocument,
    } = dto;

    const pipeline = [];

    const matchStage: any = {};

    // 连接 varTestChild 表
    pipeline.push({
      $lookup: {
        from: 'vartestchildren', // ProcessHandling 集合名称
        localField: 'varObjectId', // 当前集合中的字段
        foreignField: '_id', // 要关联集合中的字段
        pipeline: [],
        as: 'varTestChild', // 关联结果保存为的新字段名
      },
    });

    pipeline.push({
      $addFields: {
        varTestChild: { $arrayElemAt: ['$varTestChild', 0] },
      },
    });

    if (varBool != null && varBool != undefined) {
      matchStage.varBool = varBool;
    }

    if (!_.isEmpty(varString)) {
      //可以直接匹配string和string[]
      matchStage.varString = { $regex: varString, $options: 'i' };
      // matchStage.varStringArray = varString;
    }

    //不等于
    if (!_.isEmpty(varNeString)) {
      matchStage.varString = { $ne: varNeString };
    }

    if (!_.isEmpty(varNumber)) {
      matchStage.varNumber = parseInt(varNumber);
    }

    if (!_.isEmpty(varEnumStatus)) {
      matchStage.varEnumStatus = varEnumStatus;
    }

    if (!_.isEmpty(varStringArray)) {
      //varStringArray 必须传个数组
      matchStage.varStringArray = { $in: varStringArray };
    }

    //判断时间
    if (varDateStart && varDateEnd) {
      //判断时间是否在varDateStart和varDateEnd之间 这块要精准 把时分秒带上
      //传真实的起始时间，可以把数据库中数据正确的全部筛选，不用管数据库的时间，因为那个时间差8小时
      matchStage.varDate = {
        $gte: new Date(varDateStart),
        $lte: new Date(varDateEnd),
      };
    }

    //根据一个查询参数 查两个字段
    // if (!_.isEmpty(searchValue)) {
    //   matchStage.$or = [
    //     { varString: { $regex: searchValue, $options: 'i' } },
    //     // { varEnumStatus: { $regex: searchValue, $options: 'i' } }, //模糊匹配另一个字段
    //     { varStringArray: { $in: [new RegExp(searchValue, 'i')] } }, // 模糊匹配数组中的字符串
    //     // { varStringArray: searchValue }, //==精准匹配数组中的字符串
    //   ];
    // }

    //添加查询操作符
    pipeline.push({
      $match: matchStage,
    });

    //添加用户查询条件
    if (!_.isEmpty(userId)) {
      //去mysql里根据id查询人员
      const user = await this.dataBaseLinkService.getUserById(userId);
      //添加某个字段
      pipeline.push({
        $addFields: {
          user: user,
          //从文档的某个对象里取出某个值 单独提出来
          varObjectHasTypeName: { $ifNull: ['$varObjectHasType.name', null] },
          //从文档的某个数组里取出第一个
          varObjectArrayFirst: { $arrayElemAt: ['$varObjectArray', 0] },
          //从文档的某个数组里取出第一个 单独提出来name
          varObjectArrayFirstName: {
            $arrayElemAt: ['$varObjectArray.name', 0],
          },
        },
      });
    }

    //根据某个字段排序
    pipeline.push({ $sort: { createdAt: 1 } });

    //排除不想要的字段
    const projectStage = {
      $project: {
        __v: 0,
      },
    };

    pipeline.push(projectStage);

    pipeline.push({ $skip: req.herin.skip ?? 0 });
    pipeline.push({ $limit: req.herin.limit ?? 10 });

    const result: any = await this.mongodbService.VarTestModel.aggregate(
      pipeline
    );

    return {
      data: result,
      total: result ? result.length : 0,
    };
  }

  // 查询列表 使用find
  async varListByFind(dto, req) {
    //根据上面的条件 进行列表查询 - 使用管道
    const {
      searchValue,
      userId,
      varBool,
      varDateStart,
      varDateEnd,
      varEnumStatus,
      varNumber,
      varNeString,
      varStringArray,
      varNumberArray,
      varObject,
      varObjectId,
      varString,
      varSubDocument,
    } = dto;

    let findobj: any = {};

    if (!_.isEmpty(searchValue)) {
      findobj = { varString: { $regex: searchValue, $options: 'i' } };
    }

    let result = await this.mongodbService.VarTestModel.findOne(findobj)
      .select({ __v: 0 })
      .lean();
    return result;
  }

  async testsse() {
    this.sseService.sendToAllUser({
      type: 'TestSee',
      data: '我是后端传过来的数据',
    });
  }

  async testRedis() {
    await this.cacheService.set('testRedis', '我是测试redis测试数据', 6000);
    const cache = await this.cacheService.get('testRedis');
    return cache;
  }

  // 请求HTTP数据
  async getHttpData() {
    return await this.getThirdPartyData();
  }

  // 请求HTTP数据
  async postHttpData() {
    return await this.postThirdPartyData();
  }

  // 示例：调用第三方 GET 接口
  async getThirdPartyData() {
    const url = 'http://127.0.0.1:8200/scjc/getAllData';
    return this.httpRequestService.get(url);
  }

  // 示例：调用第三方 POST 接口
  async postThirdPartyData() {
    const url = 'http://127.0.0.1:8200/scjc/setAllData';
    const payload = {
      data: {
        GS: {
          GS_GB_Number: '22',
          GS_Weight: '22',
          GS_WenDu: '22',
          GS_CG_Time: '22',
          GS_C: '22',
          GS_Si: '22',
          GS_Mn: '22',
          GS_P: '22',
          GS_S: '22',
        },
      },
    };

    return this.httpRequestService.post(url, payload);
  }

  async addOperateLog() {
    //计算某段代码的执行时长
    await this.operationLogService.create(
      1,
      '测试模块',
      '测试操作类型',
      10000,
      '{}',
      '{}'
    );
    return 'ok';
  }
}
